package br.com.foxinline.manager.criar;

import br.com.foxinline.enums.Status;
import br.com.foxinline.enums.TipoAverbacao;
import br.com.foxinline.enums.TipoDocumento;
import br.com.foxinline.enums.TipoRequerimento;
import br.com.foxinline.modelo.Averbacao;
import br.com.foxinline.modelo.Coordenada;
import br.com.foxinline.modelo.Dimensao;
import br.com.foxinline.modelo.Endereco;
import br.com.foxinline.modelo.Imovel;
import br.com.foxinline.modelo.Proprietario;
import br.com.foxinline.modelo.Requerimento;
import br.com.foxinline.modelo.TramiteRequerimento;
import br.com.foxinline.modelo.Usuario;
import br.com.foxinline.servico.AverbacaoServico;
import br.com.foxinline.servico.ImovelServico;
import br.com.foxinline.servico.PrefeituraServico;
import br.com.foxinline.servico.ProprietarioServico;
import br.com.foxinline.servico.RequerimentoServico;
import br.com.foxinline.servico.TramiteRequerimentoServico;
import br.com.foxinline.servico.UsuarioServico;
import br.com.foxinline.util.Caracter;
import br.com.foxinline.util.Msg;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

/**
 *
 * @author ely
 */
@ViewScoped
@ManagedBean
public class ManagerAverbacao {

    @EJB
    private ImovelServico imovelServico;
    @EJB
    private ProprietarioServico proprietarioServico;
    @EJB
    private AverbacaoServico averbacaoServico;
    @EJB
    PrefeituraServico prefeituraServico;
    @EJB
    private UsuarioServico usuarioServico;
    @EJB
    private TramiteRequerimentoServico tramiteRequerimentoServico;
    @EJB
    private RequerimentoServico requerimentoServico;
    private Imovel imovel;
    private String imovelId;
    //Averbação mudança de Nome
    private String novoNome;
    //Averbação Transferencia
    private List<Proprietario> atuaisProprietarios;
    private List<Proprietario> novosProprietarios;
    //Averbaçao de Desmembramento
    private List<Imovel> imoveis;
    private Imovel novoImovel;
    private BigDecimal area;
    private Proprietario proprietario;
    private Averbacao averbacao;
    private Averbacao averbacaoReferente;
    private boolean btDisable;
    boolean habilitaProprietario;
    private String inscricaoImovel;
    private Requerimento requerimento;
    private Usuario usuario;
    private TramiteRequerimento tramite;
    private List<TramiteRequerimento> tramites;

    @PostConstruct
    public void init() {
        this.proprietario = new Proprietario();
        this.proprietario.setTipoDocumento(TipoDocumento.CPF);
        this.proprietario.setEndereco(new Endereco());

        this.imovel = new Imovel();
        this.imoveis = new ArrayList<Imovel>();

        this.averbacao = new Averbacao();
        iniciarNovoImovel();

        this.habilitaProprietario = false;

        paramPost();
        usuario = usuarioServico.getCurrentUser();
        tramite = new TramiteRequerimento();
        tramites = new ArrayList<TramiteRequerimento>();
    }

    private void paramPost() {

        Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        this.imovelId = params.get("imovelId");

        try {
            this.imovel = imovelServico.find(Long.parseLong(this.imovelId));
            this.atuaisProprietarios = imovel.getProprietarios();
            this.novosProprietarios = new ArrayList<Proprietario>();
//            this.imoveis.add(this.imovel);
            this.area = this.imovel.getDimensoes().getAreaTerreno();
//            this.novoImovel = this.imovel;
            this.inscricaoImovel = "";

            DecimalFormat d = new DecimalFormat("");
            d.setMinimumIntegerDigits(2);

            this.inscricaoImovel += d.format(this.imovel.getInscricaoCadastralD() == null ? 0 : this.imovel.getInscricaoCadastralD());
            this.inscricaoImovel += d.format(this.imovel.getInscricaoCadastralS() == null ? 0 : this.imovel.getInscricaoCadastralS());
            d.setMinimumIntegerDigits(3);
            this.inscricaoImovel += d.format(this.imovel.getInscricaoCadastralQuadra() == null ? 0 : this.imovel.getInscricaoCadastralQuadra());
            d.setMinimumIntegerDigits(4);
            d.setDecimalSeparatorAlwaysShown(false);
            this.inscricaoImovel += d.format(this.imovel.getInscricaoCadastralLote() == null ? 0 : this.imovel.getInscricaoCadastralLote());
            d.setMinimumIntegerDigits(2);
            this.inscricaoImovel += d.format(this.imovel.getInscricaoCadastralUnid() == null ? 0 : this.imovel.getInscricaoCadastralUnid());

        } catch (Exception e) {
            System.err.println(e);
        }
    }

    public List<Averbacao> autocomplete() {
        return averbacaoServico.getPorImovel(this.imovel);
    }

    public void limpaNovosProprietarios() {
        this.novosProprietarios = new ArrayList<Proprietario>();
    }

    public String tituloAverbacao(Averbacao r) {
        return String.format("%05d", r.getId()) + " - " + r.getTipoAverbacao().getNome() + " - " + averbacaoServico.formatDate(r.getDataAverbacao());
    }

    public void selecionaProprietario(Proprietario proprietario) {
        if (!this.novosProprietarios.contains(proprietario)) {
            this.novosProprietarios.add(proprietario);
        } else {
            Msg.messagemWarn("Proprietario já inserido.");
        }
    }

    public void salvarPorTransferencia() {

        for (Proprietario pro : novosProprietarios) {
            if (pro.getId() == null) {
                proprietarioServico.save(pro);
            }
        }

        try {
            imovel = imovelServico.find(imovel.getId());
            averbacao.setAdquirente(novosProprietarios);
            averbacao.setTransmitente(atuaisProprietarios);
            averbacao.setImovel(imovel);
            averbacao.setAverbacao(averbacaoReferente);
            averbacao.setTipoAverbacao(TipoAverbacao.TRANSFERENCIA);
            averbacao.setRequerimento(salvarRequerimento());
            averbacaoServico.save(averbacao);
            Msg.messagemInfoRedirect("Averbação realizada", "visualizarimovel.xhtml?vImovel=" + imovel.getId());

        } catch (Exception erro) {
            System.out.println(erro);
        }

    }

    public Requerimento salvarRequerimento() {
        requerimento = new Requerimento();

        if (averbacao.getTipoAverbacao() == TipoAverbacao.TRANSFERENCIA) {
            interessadoDocNome(atuaisProprietarios, requerimento);
            proprietarioDocNome(novosProprietarios, requerimento);
            requerimento.setTipoAverbacao(TipoAverbacao.TRANSFERENCIA);
        }
        if (averbacao.getTipoAverbacao() == TipoAverbacao.MUDANCA_NOME) {
            interessadoDocNome(averbacao.getImovel().getProprietarios(), requerimento);
            proprietarioDocNome(averbacao.getImovel().getProprietarios(), requerimento);
            requerimento.setTipoAverbacao(TipoAverbacao.MUDANCA_NOME);
        }
        if (averbacao.getTipoAverbacao() == TipoAverbacao.DESMEMBRAMENTO) {
            interessadoDocNome(averbacao.getImovel().getProprietarios(), requerimento);
            proprietarioDocNome(averbacao.getImovel().getProprietarios(), requerimento);
            requerimento.setTipoAverbacao(TipoAverbacao.DESMEMBRAMENTO);
        }

        requerimento.setAtivo(true);
        requerimento.setStatus(Status.DOCPENDENTE);
        requerimento.setTipoRequerimento(TipoRequerimento.AVERBACAO);

        tramite = getTramiteRequerimento();
        tramites.add(tramite);

        for (TramiteRequerimento t : tramites) {
            tramiteRequerimentoServico.save(t);
        }

        requerimento.setTramites(tramites);

        requerimentoServico.save(requerimento);

        return requerimento;
    }

    public TramiteRequerimento getTramiteRequerimento() {
        TramiteRequerimento t = new TramiteRequerimento();
        t.setDataTramite(new Date());
        t.setStatus(requerimento.getStatus());
        t.setUsuario(usuario);
        return t;
    }

    private void interessadoDocNome(List<Proprietario> proprietarios, Requerimento requerimento) {

        Proprietario p = proprietarios.get(0);


        if (p.getTipoDocumento() == TipoDocumento.CNPJ) {
            requerimento.setTipoDocumentoInteressado(TipoDocumento.CNPJ);
            requerimento.setCnpjInteressado(p.getCnpj());
            requerimento.setNomeFantasiaInteressado(p.getNomeFantasia());
            if (p.getEndereco() != null) {
                requerimento.setEnderecoInteressado(p.getEndereco().getLogradouro());
                requerimento.setBairroInteressado(p.getEndereco().getBairro());
                requerimento.setCepInteressado(p.getEndereco().getCep());
                requerimento.setNumInteressado(p.getEndereco().getNumero());
            }
        } else if (p.getTipoDocumento() == TipoDocumento.CPF) {
            requerimento.setTipoDocumentoInteressado(TipoDocumento.CPF);
            requerimento.setCpfInteressado(p.getCpf());
            requerimento.setNomeInteressado(p.getNome());
            if (p.getEndereco() != null) {
                requerimento.setEnderecoInteressado(p.getEndereco().getLogradouro());
                requerimento.setBairroInteressado(p.getEndereco().getBairro());
                requerimento.setCepInteressado(p.getEndereco().getCep());
                requerimento.setNumInteressado(p.getEndereco().getNumero());
            }
        }

        requerimento.setEnderecoImovel(imovel.getEnderecoImovel().getLogradouro());
        requerimento.setBairroImovel(imovel.getEnderecoImovel().getBairro());
        requerimento.setCepImovel(imovel.getEnderecoImovel().getCep());
        requerimento.setNumImovel(imovel.getEnderecoImovel().getNumero());
    }

    private void proprietarioDocNome(List<Proprietario> proprietarios, Requerimento requerimento) {

        Proprietario p = proprietarios.get(0);

        if (p.getTipoDocumento() == TipoDocumento.CNPJ) {
            requerimento.setTipoDocumentoProprietario(TipoDocumento.CNPJ);
            requerimento.setCnpjProprietario(p.getCnpj());
            requerimento.setNomeFantasiaProprietario(p.getNomeFantasia());
        } else if (p.getTipoDocumento() == TipoDocumento.CPF) {
            requerimento.setTipoDocumentoProprietario(TipoDocumento.CPF);
            requerimento.setCpfProprietario(p.getCpf());
            requerimento.setNomeProprietario(p.getNome());
        }
    }

    public List<SelectItem> tipoDocumentoList() {
        List<SelectItem> items = new ArrayList<SelectItem>();
        for (TipoDocumento tipo : TipoDocumento.values()) {
            items.add(new SelectItem(tipo.getTipo(), tipo.getNome()));
        }
        return items;
    }

    public void salvarAverbacaoMudancaNome() {
        try {

            String antigoNome = this.proprietario.getNome();

            averbacao.setAverbacao(averbacaoReferente);
            averbacao.setNomeAnterior(antigoNome);
            averbacao.setNomeAtual(novoNome);
            averbacao.setCpfNomeAnterior(proprietario.getCpf());
            averbacao.setCpfNomeAtual(proprietario.getCpf());
            averbacao.setImovel(imovel);
            averbacao.setTipoAverbacao(TipoAverbacao.MUDANCA_NOME);
            averbacao.setRequerimento(salvarRequerimento());
            averbacaoServico.save(averbacao);
            Msg.messagemInfoRedirect("Averbação realizada.", "visualizarimovel.xhtml?vImovel=" + imovel.getId());
        } catch (Exception e) {

            System.err.println(e);
            Msg.messagemError("Erro ao atualizar/salvar a averbação !");
        }
//        try {
//
//            proprietario.setNome(novoNome);
//            proprietarioServico.update(proprietario);
//            RequestContext requestContext = RequestContext.getCurrentInstance();
//            requestContext.execute("printDialog.show()");
//
//        } catch (Exception e) {
//
//            System.err.println(e);
//            Msg.messagemError("Erro ao atualizar o proprietário !");
//        }


    }

    public void mudarProprietario(Proprietario p) {
        this.proprietario = p;
        this.novoNome = this.proprietario.getNome();
    }

    public void imprimirAverbacao(Averbacao averbacao) {
        HashMap parametros = new HashMap();

        parametros.putAll(prefeituraServico.parametroPrefeitura());

        averbacaoServico.imprimirAverbacao(averbacao, parametros);

    }

    public void redirect() {
        Msg.messagemInfoRedirect("Averbação realizada", "visualizarimovel.xhtml?vImovel=" + imovel.getId());
    }

    public void addProprietario() {
        this.proprietario.setCpf(Caracter.removecaracter(this.proprietario.getCpf()));
        this.proprietario.setCnpj(Caracter.removecaracter(this.proprietario.getCnpj()));

        this.novosProprietarios.add(this.proprietario);

        this.proprietario = new Proprietario();
        this.proprietario.setTipoDocumento(TipoDocumento.CPF);
        this.proprietario.setEndereco(new Endereco());
    }

    public void removeProprietario(Proprietario proprietario) {
        this.novosProprietarios.remove(proprietario);
    }

    //Métodos para Desmembramento
    public void salvarAverbacaoDesmembramento() {

        if (this.imovel.getDimensoes().getAreaTerreno().compareTo(new BigDecimal(BigInteger.ZERO)) == 0) {
            this.imovel = imovelServico.find(this.imovel.getId());
            this.imovel.setInscricaoCanceladaPorDesmembramento(true);
//
//            imovelServico.update(this.imovel); 

            this.averbacao = new Averbacao();
//            this.averbacao.setImoveis(this.imoveis);
            this.averbacao.setImovel(this.imovel);
            this.averbacao.setTipoAverbacao(TipoAverbacao.DESMEMBRAMENTO);
            this.averbacao.setDataAverbacao(new Date());
            this.averbacao.setRequerimento(salvarRequerimento());

            for (Imovel i : this.imoveis) {
                i.setAtivo(false);

            }

            this.averbacao.setImoveis(this.imoveis);
            averbacaoServico.update(this.averbacao);
            Msg.messagemInfoRedirect("Desmembramento realizado", "visualizarimovel.xhtml?vImovel=" + imovel.getId());
        } else {
            Msg.messagemError("A área total desmembrada não corresponde a área total do imóvel !");
        }
    }

    public void addImovel() {

        if (this.novoImovel.getDimensoes().getAreaTerreno() != null && this.novoImovel.getDimensoes().getAreaTerreno().compareTo(this.area) <= 0) {

            this.area = desmembrar(this.novoImovel);
            this.novoImovel.setProprietarios(this.novosProprietarios);
            this.imoveis.add(this.novoImovel);
            this.imovel.getDimensoes().setAreaTerreno(this.area);
            this.btDisable = true;
            iniciarNovoImovel();
        } else {

            this.imovel.getDimensoes().setAreaTerreno(this.area);
            Msg.messagemWarn("Área maior do que a disponível !");
            this.btDisable = false;
        }
    }

    public void removeImovel(Imovel imovel) {
        this.area = this.area.add(imovel.getDimensoes().getAreaTerreno());
        this.imovel.getDimensoes().setAreaTerreno(this.area);
        this.imoveis.remove(imovel);
    }

    public void editarImovel(Imovel imovel) {
        this.novoImovel = imovel;
        this.novosProprietarios = this.novoImovel.getProprietarios();
        removeImovel(imovel);
    }

    public BigDecimal desmembrar(Imovel novoImovel) {
        return this.area.subtract(novoImovel.getDimensoes().getAreaTerreno());
    }

    public Imovel novoImovel(Imovel antigoImovel) throws CloneNotSupportedException {
        Imovel i = antigoImovel.clone();

        i.setLadoDireito(this.novoImovel.getLadoDireito());
        i.setLadoEsquerdo(this.novoImovel.getLadoEsquerdo());
        i.setFrente(this.novoImovel.getFrente());
        i.setFundo(this.novoImovel.getFundo());
        i.setProprietarios(this.novosProprietarios);
        i.setDimensoes(this.novoImovel.getDimensoes().clone());
        i.setImovel(this.imovel);

        return i;
    }

    public void redirectAverbacao() throws IOException {
        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
        context.redirect("visualizarimovel.xhtml?vImovel=" + this.imovel.getId());
    }

    public void usarInformacoesImovelAntigo(boolean usar) {

        if (usar) {

            this.novoImovel.setEnderecoImovel(this.imovel.getEnderecoImovel());
            this.novoImovel.getEnderecoImovel().setNumero(null);

            this.novoImovel.setEnderecoCorrespondencia(this.imovel.getEnderecoCorrespondencia());
            this.novoImovel.getEnderecoCorrespondencia().setNumero(null);

            if (this.novosProprietarios == null) {
                this.novosProprietarios = new ArrayList<Proprietario>();
            }

            this.novosProprietarios.addAll(this.imovel.getProprietarios());

            this.novoImovel.setProprietarios(this.novosProprietarios);

            this.novoImovel.setCalcamento(this.imovel.getCalcamento());
            this.novoImovel.setIluminacaoPublica(this.imovel.getIluminacaoPublica());
            this.novoImovel.setColetaLixo(this.imovel.getColetaLixo());
            this.novoImovel.setLimpezaPublica(this.imovel.getLimpezaPublica());
            this.novoImovel.setLocalizacao(this.imovel.getLocalizacao());
            this.novoImovel.setPedologia(this.imovel.getPedologia());
            this.novoImovel.setPosicao(this.imovel.getPosicao());
            this.novoImovel.setTopografia(this.imovel.getTopografia());

            this.novoImovel.setFrente(this.imovel.getFrente());
            this.novoImovel.setFrenteMedindo(this.imovel.getFrenteMedindo());
            this.novoImovel.setFrenteRua(this.imovel.getFrenteRua());

            this.novoImovel.setLadoDireito(this.imovel.getLadoDireito());
            this.novoImovel.setLadoDireitoMedindo(this.imovel.getLadoDireitoMedindo());
            this.novoImovel.setLadoDireitoRua(this.imovel.getLadoDireitoRua());

            this.novoImovel.setLadoEsquerdo(this.imovel.getLadoEsquerdo());
            this.novoImovel.setLadoEsquerdoMedindo(this.imovel.getLadoEsquerdoMedindo());
            this.novoImovel.setLadoEsquerdoRua(this.imovel.getLadoEsquerdoRua());

            this.novoImovel.setFundo(this.imovel.getFundo());
            this.novoImovel.setFundoMedindo(this.imovel.getFundoMedindo());
            this.novoImovel.setFundoRua(this.imovel.getFundoRua());

            if (this.novoImovel.getCoordenadas() != null && !this.novoImovel.getCoordenadas().isEmpty()) {

                Coordenada coordenada = this.novoImovel.getCoordenadas().get(0);
                coordenada.setId(null);

                this.novoImovel.getCoordenadas().clear();
                this.novoImovel.getCoordenadas().add(coordenada.getClone());
            }
        } else {
            iniciarNovoImovel();
            this.novosProprietarios = new ArrayList<Proprietario>();
        }
    }

    private void iniciarNovoImovel() {
        this.novoImovel = new Imovel();
        this.novoImovel.setDimensoes(new Dimensao());
        this.novoImovel.setProprietarios(new ArrayList<Proprietario>());
    }

    public String nomeDosProprietarios(Imovel imovel) {
        return averbacaoServico.getNomeProprietarios(imovel.getProprietarios());
    }

    public Averbacao getAverbacaoReferente() {
        return averbacaoReferente;
    }

    public void setAverbacaoReferente(Averbacao averbacaoReferente) {
        this.averbacaoReferente = averbacaoReferente;
    }

    public Averbacao getAverbacao() {
        return averbacao;
    }

    public void setAverbacao(Averbacao averbacao) {
        this.averbacao = averbacao;
    }

    public List<Proprietario> getAtuaisProprietarios() {
        return atuaisProprietarios;
    }

    public void setAtuaisProprietarios(List<Proprietario> atuaisProprietarios) {
        this.atuaisProprietarios = atuaisProprietarios;
    }

    public List<Proprietario> getNovosProprietarios() {
        return novosProprietarios;
    }

    public void setNovosProprietarios(List<Proprietario> novosProprietarios) {
        this.novosProprietarios = novosProprietarios;
    }

    public Proprietario getProprietario() {
        return proprietario;
    }

    public void setProprietario(Proprietario proprietario) {
        this.proprietario = proprietario;
    }

    public Imovel getImovel() {
        return imovel;
    }

    public void setImovel(Imovel imovel) {
        this.imovel = imovel;
    }

    public String getNovoNome() {
        return novoNome;
    }

    public void setNovoNome(String novoNome) {
        this.novoNome = novoNome;
    }

    public List<Imovel> getImoveis() {
        return imoveis;
    }

    public void setImoveis(List<Imovel> imoveis) {
        this.imoveis = imoveis;
    }

    public Imovel getNovoImovel() {
        return novoImovel;
    }

    public void setNovoImovel(Imovel novoImovel) {
        this.novoImovel = novoImovel;
    }

    public BigDecimal getArea() {
        return area;
    }

    public void setArea(BigDecimal area) {
        this.area = area;
    }

    public boolean isBtDisable() {
        return btDisable;
    }

    public void setBtDisable(boolean btDisable) {
        this.btDisable = btDisable;
    }

    public boolean isHabilitaProprietario() {
        return habilitaProprietario;
    }

    public void setHabilitaProprietario(boolean habilitaProprietario) {
        this.habilitaProprietario = habilitaProprietario;
    }

    public String getInscricaoImovel() {
        return inscricaoImovel;
    }

    public void setInscricaoImovel(String inscricaoImovel) {
        this.inscricaoImovel = inscricaoImovel;
    }
}
